home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
pascal
/
p_mat.exe
/
PMAT.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1993-01-23
|
24KB
|
895 lines
{
P-Mat - A Turbo Pascal program for Recursive Matrix Algebra
Version: 1.2
Author: Mark Von Tress, Ph.D.
Date: 01/30/93
Copyright(c) Mark Von Tress 1993
DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
FROM USE OF THIS PROGRAM.
}
Unit pmat;
Interface
Type
fp = ^double;
ap = Array[1..1] Of double;
apptr = ^ap;
app = Array[1..1] Of apptr;
vmatrixptr = ^vmatrix;
vmatrix = Object
r, c : integer;
Function m( i, j: integer ): double;
Function mm( i, j: integer ) : fp;
constructor MakeMatrix( vr, vc: integer );
Destructor KillVmatrix;
Procedure Garbage;
Procedure Show( strng: String );
Procedure infomatrix( strng: String );
private
v,vcheck: ^app;
nelems : longint;
onstack : boolean;
Procedure purgevectors;
Procedure allocvectors( rr, cc: integer );
End;
mstackptr = ^mstack;
mstack = Object
constructor InitMatrixStack;
Destructor KillMatrixStack;
Procedure inclevel;
Procedure declevel;
Function ReturnMat: vmatrixptr;
Function DecReturn: vmatrixptr;
Procedure push( Var a: vmatrixptr );
Procedure nrerror( strng: String );
Procedure DumpStack;
private
nummats, level : integer;
next : mstackptr;
mv : vmatrixptr;
Procedure cleanstack( a: vmatrixptr );
Function pop: vmatrixptr;
End;
Var
dispatch : mstackptr;
Function matequals( Var lop: vmatrixptr; rop: vmatrixptr ) : vmatrixptr;
Function ident( n: integer ): vmatrixptr;
Function Mult( A, B: vmatrixptr ):vmatrixptr;
Function emult( a, b: vmatrixptr ):vmatrixptr;
Function scmult( a: double; b: vmatrixptr ): vmatrixptr;
Function multsc( b: vmatrixptr; a: double ): vmatrixptr;
Function divis( a, b: vmatrixptr ):vmatrixptr;
Function scdivis( a: double; b: vmatrixptr ): vmatrixptr;
Function divissc( b: vmatrixptr; a: double ): vmatrixptr;
Function add( a, b: vmatrixptr ): vmatrixptr;
Function scadd( a: double; b: vmatrixptr ): vmatrixptr;
Function addsc( b: vmatrixptr; a: double ): vmatrixptr;
Function neg( A: vmatrixptr ): vmatrixptr;
Function sub( A, B: vmatrixptr ):vmatrixptr;
Function scsub( A: double; B: vmatrixptr ):vmatrixptr;
Function subsc( B: vmatrixptr; A: double ):vmatrixptr;
Function tran( a: vmatrixptr ): vmatrixptr;
Function sweep( A: vmatrixptr; k1, k2: integer ) : vmatrixptr;
Function inv( Amat: vmatrixptr ): vmatrixptr;
Function fill( rr, cc: integer; d: double ):vmatrixptr;
Function submat( a: vmatrixptr; lr, r, lc, c: integer ): vmatrixptr;
Function cv( a, b: vmatrixptr ): vmatrixptr;
Function ch( a, b: vmatrixptr ): vmatrixptr;
Function vecdiag( a: vmatrixptr ): vmatrixptr;
Function reada( fid: String ): vmatrixptr;
Procedure writea( fid: String; a: vmatrixptr; titlestr: String );
Procedure setwid( wid: integer );
Procedure setdec( decimals: integer );
Function getwid: integer;
Function getdec: integer;
Implementation
{///////////////// vmatrix functions ///////////////}
{$R-}
Procedure vmatrix.allocvectors;
Var i: integer;
Begin
if c > 8192 then
dispatch^.nrerror('A matrix cannot have more than 8192 columns');
getmem( v, r * sizeof( apptr ) );
For i := 1 To r Do
getmem( v^[i], c * sizeof( double ) );
End;
Procedure vmatrix.purgevectors;
Var i: integer;
Begin
If v = Nil Then exit;
For i := r Downto 1 Do
freemem( v^[i], c * sizeof( double ) );
freemem( v, r * sizeof( apptr ) );
End;
{$R+}
constructor vmatrix.MakeMatrix;
Begin
r := vr;
c := vc;
onstack := false;
if c > 8192 then
dispatch^.nrerror('A matrix cannot have more than 8192 columns');
nelems := longint( longint( r ) * longint( c ) ) * longint( sizeof( double ) );
If nelems < maxAvail - 256 Then allocvectors( r, c )
Else dispatch^.nrerror( 'cannot allocate matrix' );
vcheck := v;
End; { MakeMatrix }
Destructor vmatrix.KillVmatrix;
Begin
purgevectors;
vcheck := Nil;
End;
Procedure vmatrix.Garbage;
Var errorint : boolean;
Begin
errorint := false;
If vcheck <> v Then errorint := true;
If v = Nil Then errorint := true;
If r < 1 Then errorint := true;
If c < 1 Then errorint := true;
If errorint Then dispatch^.Nrerror( 'garbage' );
End;
{$R-}
Function vmatrix.m;
Begin
{ access a member on the right side of assignment }
If ( i < 1 ) Or( j < 1 ) Or( i > r ) Or( j > c ) Then
dispatch^.nrerror( 'm: index out of range' );
m := v^[i]^[j];
End;
Function vmatrix.mm;
Begin
{ store a matrix element on the left side of assignment }
If ( i < 1 ) Or( j < 1 ) Or( i > r ) Or( j > c ) Then
dispatch^.nrerror( 'mm: index out of range' );
mm := @v^[i]^[j];
End;
{$R+}
Procedure CopySD( Var source, dest: vmatrixptr );
Var
i,j : integer;
Begin
source^.Garbage;
dest^.Garbage;
If source = dest Then exit;
If source^.onstack Then
With dest^ Do Begin
purgevectors;
nelems := source^.nelems;
v := dispatch^.Pop^.v;
r := source^.r;
c := source^.c;
vcheck := v;
source^.v := Nil;
dispose( source, killvmatrix );
exit;
End;
If source^.v = dest^.v Then
With dest^ Do Begin
r := source^.r;
c := source^.c;
allocvectors( r, c );
vcheck := v;
nelems := source^.nelems;
End;
If ( dest^.r <> source^.r ) Or( dest^.c <> source^.c ) Then
With dest^ Do Begin
purgevectors;
r := source^.r;
c := source^.c;
allocvectors( r, c );
vcheck := v;
nelems := source^.nelems;
End;
For i := 1 To dest^.r Do
For j := 1 To dest^.c Do
dest^.mm( i, j )^ := source^.m( i, j );
End;
Function matequals;
Begin
rop^.Garbage;
lop^.Garbage;
copySD( rop, lop );
dispatch^.CleanStack( lop );
matequals := lop;
End;
{////////////////////// stack functions /////////}
constructor mstack.InitMatrixStack;
Begin
nummats := 0;
level := 1;
mv := Nil;
getmem( next, sizeof( mstack ) );
With next^ Do Begin
level := 0;
next := Nil;
mv := Nil;
nummats := 0;
End;
End;
Destructor mstack.KillMatrixStack;
Begin
freemem( next, sizeof( mstack ) );
End;
Procedure mstack.nrerror;
Begin
writeln( 'Fatal Error: ', strng );
writeln( 'Exiting to system' );
halt;
End;
Procedure mstack.inclevel;
Begin
level := level + 1;
End;
Procedure mstack.declevel;
Begin
level := level - 1;
If level <= 0 Then nrerror( 'declevel: decremented too often' );
End;
Function mstack.ReturnMat;
Begin
ReturnMat := next^.mv;
End;
Function mstack.DecReturn;
Begin
declevel;
DecReturn := next^.mv;
End;
Procedure mstack.push;
Var
t : mstackptr;
Begin
a^.Garbage;
getmem( t, sizeof( mstack ) );
t^.level := dispatch^.level;
t^.next := dispatch^.next;
t^.mv := a;
a^.onstack := true;
dispatch^.next := t;
dispatch^.nummats := dispatch^.nummats + 1;
t^.nummats := dispatch^.nummats;
End;
Function mstack.pop;
Var t : mstackptr;
vv : vmatrixptr;
Begin
If dispatch^.level < 0 Then
nrerror( 'pop: missmatched inclevel-declevel statments, level < 0' );
If ( dispatch^.next^.next = Nil ) Or( Nil = dispatch^.next^.mv ) Then
nrerror( 'pop: popping off the tail' );
t := dispatch^.next;
dispatch^.next := di